package com.example.flow.flow.model;

import com.example.flow.flow.ClassHelper;
import com.example.flow.flow.FlowNodeInterceptor;
import com.example.flow.flow.core.Execution;
import com.example.flow.flow.core.SpringContext;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 节点元素
 *
 * @author tangaq
 * 2023/6/13
 */
public abstract class NodeModel extends BaseModel {
    private static final long serialVersionUID = 7546463903958367813L;
    private static final Logger log = LoggerFactory.getLogger(NodeModel.class);
    /**
     * 前置拦截器
     */
    private String preInterceptors;
    /**
     * 后置拦截器
     */
    private String postInterceptors;

    @JsonIgnore
    private TransitionModel nextNode;

    @JsonIgnore
    private List<FlowNodeInterceptor> preInterceptorList = new ArrayList<>();

    @JsonIgnore
    private List<FlowNodeInterceptor> postInterceptorList = new ArrayList<>();

    protected abstract void exec(Execution exception);

    public void execute(Execution execution) {
        if (!(this instanceof TaskModel)) {
            // 如果不是任务节点则执行前置拦截
            intercept(preInterceptorList, execution);
        }
        exec(execution);
    }

    public void doPreIntercept(Execution execution) {
        intercept(preInterceptorList, execution);
    }

    public void doPostIntercept(Execution execution) {
        intercept(postInterceptorList, execution);
    }

    private void intercept(List<FlowNodeInterceptor> interceptorList, Execution exception) {
        for (FlowNodeInterceptor interceptor : interceptorList) {
            try {
                interceptor.intercept(exception);
            } catch (Exception e) {
                log.error("拦截器执行失败:{}", e.getMessage(), e);
                throw new RuntimeException(e);
            }
        }
    }

    public TransitionModel getNextNode() {
        return nextNode;
    }

    public void setNextNode(TransitionModel nextNode) {
        this.nextNode = nextNode;
    }

    protected void runNextNode(Execution execution) {
        // 进入节点后执行
        intercept(postInterceptorList, execution);
        TransitionModel nextNode = getNextNode();
        if (nextNode != null && nextNode.getTarget() != null) {
            nextNode.execute(execution);
        }
    }

    public void setPreInterceptors(String preInterceptors) {
        this.preInterceptors = preInterceptors;
        if (StringUtils.isNotEmpty(preInterceptors)) {
            for (String interceptor : preInterceptors.split(",")) {
                FlowNodeInterceptor instance = (FlowNodeInterceptor) SpringContext.getBean(getClazz(interceptor));
                this.preInterceptorList.add(instance);
            }
        }
    }

    public void setPostInterceptors(String postInterceptors) {
        this.postInterceptors = postInterceptors;
        if (StringUtils.isNotEmpty(postInterceptors)) {
            for (String interceptor : postInterceptors.split(",")) {
                Class<?> clazz = getClazz(interceptor);
                if (clazz != null) {
                    FlowNodeInterceptor instance = (FlowNodeInterceptor) SpringContext.getBean(clazz);
                    this.postInterceptorList.add(instance);
                }
            }
        }
    }

    private Class<?> getClazz(String interceptor) {
        try {
            return ClassHelper.loadClass(interceptor);
        } catch (Exception e) {
            log.error("加载class异常,{}", interceptor, e);
        }
        return null;
    }

    public String getPreInterceptors() {
        return preInterceptors;
    }

    public String getPostInterceptors() {
        return postInterceptors;
    }

    public List<FlowNodeInterceptor> getPreInterceptorList() {
        return preInterceptorList;
    }

    public List<FlowNodeInterceptor> getPostInterceptorList() {
        return postInterceptorList;
    }
}
